package org.ysu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.minio.errors.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.multipart.MultipartFile;
import org.ysu.core.YsuException;
import org.ysu.entity.Admin;
import org.ysu.entity.SysResource;
import org.ysu.mapper.AdminMapper;
import org.ysu.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.ysu.util.JwtUtil;
import org.ysu.vo.LoginVO;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 管理员表 服务实现类
 * </p>
 *
 * @author LiuShuo
 * @since 2024-08-14
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Resource
    MailService mailService;
    @Resource
    CodeService codeService;
    @Resource
    PasswordEncoder passwordEncoder;
    @Resource
    UploadFileService uploadFileService;
    @Resource
    AdminMapper adminMapper;
    @Resource(name = "myredis")
    private RedisTemplate redisTemplate;
    @Resource
    SysResourceService sysResourceService;
    @Resource
    ProvincesService provincesService;
    @Resource
    CitiesService citiesService;
    @Resource
    AreasService areasService;
    @Resource
    TownsService townsService;

    @Override
    public List<Admin> getList() {
        QueryWrapper<Admin> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 1);
        return this.list(wrapper);
    }

    @Override
    public boolean check(Long id, String field, String value) {
        QueryWrapper<Admin> wrapper = new QueryWrapper<>();
        wrapper.eq(field, value);
        System.out.println(id);
        if (null != id) {
            wrapper.ne("id", id);
        }
        return this.count(wrapper) == 0;
    }

    @Override
    public boolean add(String name, Integer sex, String phone, String idcard, String email, String password, Long areaId, MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return this.save(new Admin(name, sex, phone, idcard, email ,passwordEncoder.encode(password), areaId
               , uploadFileService.upload("images", file)));
    }

    @Override
    public boolean update(Long id, String name, Long areaId, String phone, Integer sex, String idcard, String email, MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        Admin admin = new Admin(
                id, name, areaId, phone, sex, idcard, email
        );
        if (null != file) {
            admin.setIcon(uploadFileService.upload("images", file));
        }
        return this.updateById(admin);
    }


    @Override
    public boolean del(Long id, Boolean status) {
        return this.updateById(new Admin(id, status));
    }

    @Override
    public List<String> getNameByAdminId(Long adminId) {
        return adminMapper.getNameByAdminId(adminId);
    }

    @Override
    public LoginVO login(String username, String password) {
        Admin admin = validateLogin(username,password);
        return new LoginVO(JwtUtil.create(admin),this.getResourceByAdminId(admin.getId()), admin.getId(),admin.getAreaId());
    }
    private Admin validateLogin(String username,String password){
        QueryWrapper<Admin> wrapper=new QueryWrapper<>();
        wrapper.eq("phone",username)
                .or().eq("email",username);
        Admin admin = this.getOne(wrapper);
        if(null==admin || !passwordEncoder.matches(password,admin.getPassword())){
            throw new YsuException("用户名或密码错误");
        }
        if(!admin.getStatus()){
            throw new YsuException("管理员已经禁用，无法登录");
        }
        return admin;
    }
    public List<SysResource> getResourceByAdminId(Long adminId){
        List<SysResource> menu = new ArrayList<>();
        Set<String> backUrls = new HashSet<>();
        List<SysResource> source = sysResourceService.getByAdminId(adminId);
        for (SysResource sysResource : source) {
            if (sysResource.getType().intValue() == 1){
                if (sysResource.getParentId().intValue() == 0){
                    menu.add(sysResource);
                }else {
                    for (SysResource parent : source){
                        if(parent.getId().intValue() == sysResource.getParentId().intValue()){
                            List<SysResource> children = parent.getChildren();
                            if (null == children){
                                children = new ArrayList<>();
                                parent.setChildren(children);
                            }
                            children.add(sysResource);
                            break;
                        }
                    }
                }
            }
            if(StringUtils.isNoneBlank(sysResource.getBackUrl())){
                String[] backs = sysResource.getBackUrl().split("\\,");
                for (String url : backs){
                    backUrls.add(url.trim());
                }
            }
        }
        redisTemplate.opsForValue().set("admin::" + adminId + "::resource",backUrls,7,TimeUnit.DAYS);
        System.out.println(backUrls);
        return menu;
    }
    @Override
    public boolean sendCode(String email) throws MessagingException {
        //生成验证码
        String code = codeService.generateCode(6);
        //把验证码存入redis中去
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set(email,code,5, TimeUnit.MINUTES);
        //发邮件
        String subject = "防返贫检测系统注册邮箱验证码";
        String text = "<h1>【防返贫监测系统】您的验证码是" + code +"，在5分钟内有效。如非本人操作请忽略本邮件。</h1>";
        mailService.send(email,subject,text);
        return true;
    }

    @Override
    public boolean checkCode(String email, String code) {
        //从redis中获取验证码
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String existCode =(String) valueOperations.get(email);
        return code.equals(existCode);
    }

    @Override
    public boolean register(String name, Integer sex, String idcard, String phone,String email, String password, Long areaId) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        //System.out.println(password);
        return this.save(new Admin(name,sex,idcard,phone,email,passwordEncoder.encode(password),areaId));
    }

    @Override
    public IPage<Admin> list(Integer pageNo, Integer pageSize, String val) {
        QueryWrapper<Admin> wrapper = new QueryWrapper<>();
        if (StringUtils.isBlank(val)) {
            val = null;
        }
        return adminMapper.selectPage(new Page<>(pageNo, pageSize), val);
    }

    @Override
    public List<Admin> Verifier() {
        return adminMapper.Verifier();
    }

    @Override
    public Admin getOne(Long id) {
        Admin admin = this.getById(id);
        Long areaId = admin.getAreaId();
        if ( areaId != null && areaId > 0){
            String areaIdStr = admin.getAreaId().toString();
            if (areaIdStr.length()==2) {
                admin.setProvince(provincesService.getNameById(areaId));
            } else if (areaIdStr.length()==4) {
                admin.setProvince(provincesService.getNameById(areaId/100));
                admin.setCity(citiesService.getNameById(areaId));
            } else if (areaIdStr.length()==6) {
                admin.setProvince(provincesService.getNameById(areaId/10000));
                admin.setCity(citiesService.getNameById(areaId/100));
                admin.setCounty(areasService.getNameById(areaId));
            } else if (areaIdStr.length()==9) {
                admin.setProvince(provincesService.getNameById(areaId/10000000));
                admin.setCity(citiesService.getNameById(areaId/100000));
                admin.setCounty(areasService.getNameById(areaId/1000));
                admin.setTownship(townsService.getNameById(areaId));
            }
        }
        return admin;
    }
    @Override
    public Boolean change(String email, String password) {
        QueryWrapper<Admin> wrapper=new QueryWrapper<>();
        wrapper.eq("email",email);
        Admin admin = this.getOne(wrapper);
        if (admin != null) {
            admin.setPassword(passwordEncoder.encode(password));
        }
        return this.updateById(admin);
    }
}
